package com.wwd.statemachine.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wwd.statemachine.domain.Order;
import com.wwd.statemachine.enums.OrderFactoryStatus;
import com.wwd.statemachine.enums.OrderFactoryStatusChangeEvent;
import com.wwd.statemachine.enums.OrderStatus;
import com.wwd.statemachine.enums.OrderStatusChangeEvent;
import com.wwd.statemachine.listener.OrderStateFactoryListener;
import com.wwd.statemachine.mapper.OrderMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wangweidong
 * @date 2025-06-24 16:32
 * @description 描述
 */
@Slf4j
@Service("orderFactoryService")
public class OrderFactoryService extends ServiceImpl<OrderMapper, Order> {
    @Resource
    private StateMachineFactory<OrderFactoryStatus, OrderFactoryStatusChangeEvent> orderStateMachineFactory;
    @Resource
    private OrderStateFactoryListener orderStateFactoryListener;
    @Resource
    private OrderMapper orderMapper;

    @Resource
    // 内存存储状态机记忆 服务重启即丢失
    private StateMachinePersister<OrderFactoryStatus, OrderFactoryStatusChangeEvent, String> stateMachineRedisPersister;



    private final Map<String, StateMachine<OrderFactoryStatus, OrderFactoryStatusChangeEvent>> stateMachines = new ConcurrentHashMap<>();
    /**
     * 创建订单
     *
     * @param order
     * @return
     */
    public Order create(Order order) {
        order.setStatus(OrderFactoryStatus.WAIT_PAYMENT.getKey());
        orderMapper.insert(order);
        return order;
    }
    /**
     * 对订单进行支付
     *
     * @param id
     * @return
     */
    public Order pay(Long id) {
        Order order = orderMapper.selectById(id);
        log.info("线程名称：{},尝试支付，订单号：{}" ,Thread.currentThread().getName() , id);
        if (!sendEvent(OrderFactoryStatusChangeEvent.PAYED, order)) {
            log.error("线程名称：{},支付失败, 状态异常，订单信息：{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("支付失败, 订单状态异常");
        }
        return order;
    }
    /**
     * 对订单进行发货
     *
     * @param id
     * @return
     */
    public Order deliver(Long id) {
        Order order = orderMapper.selectById(id);
        log.info("线程名称：{},尝试发货，订单号：{}" ,Thread.currentThread().getName() , id);
        if (!sendEvent(OrderFactoryStatusChangeEvent.DELIVERY, order)) {
            log.error("线程名称：{},发货失败, 状态异常，订单信息：{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("发货失败, 订单状态异常");
        }
        return order;
    }
    /**
     * 对订单进行确认收货
     *
     * @param id
     * @return
     */
    public Order receive(Long id) {
        Order order = orderMapper.selectById(id);
        log.info("线程名称：{},尝试收货，订单号：{}" ,Thread.currentThread().getName() , id);
        if (!sendEvent(OrderFactoryStatusChangeEvent.RECEIVED, order)) {
            log.error("线程名称：{},收货失败, 状态异常，订单信息：{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("收货失败, 订单状态异常");
        }
        return order;
    }
    /**
     * 发送订单状态转换事件
     * 状态机工厂不需要进行同步处理
     *
     * @param changeEvent
     * @param order
     * @return
     */
    private boolean sendEvent(OrderFactoryStatusChangeEvent changeEvent, Order order) {
//        StateMachine<OrderFactoryStatus, OrderFactoryStatusChangeEvent> orderStateMachine =getStateMachine(String.valueOf(order.getId()));
        StateMachine<OrderFactoryStatus, OrderFactoryStatusChangeEvent> orderStateMachine = orderStateMachineFactory.getStateMachine();

        orderStateMachine.getId();
        boolean result = false;
        try {
            // 启动状态机
            orderStateMachine.start();
            // 尝试恢复状态机状态
            stateMachineRedisPersister.restore(orderStateMachine, String.valueOf(order.getId()));
            Message<OrderFactoryStatusChangeEvent> message = MessageBuilder.withPayload(changeEvent)
                    .setHeader("order", order)
                    .build();
            result = orderStateMachine.sendEvent(message);
            // 持久化状态机状态
            stateMachineRedisPersister.persist(orderStateMachine, String.valueOf(order.getId()));
        } catch (Exception e) {
            log.error("订单操作失败:{}", e);
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }

    /**
     * 获取订单对应的状态机实例
     * @param orderId 订单ID（唯一标识）
     * @return 状态机实例
     */
    public StateMachine<OrderFactoryStatus, OrderFactoryStatusChangeEvent> getStateMachine(String orderId) {
        return stateMachines.computeIfAbsent(orderId, id -> {
            StateMachine<OrderFactoryStatus, OrderFactoryStatusChangeEvent> machine = orderStateMachineFactory.getStateMachine();
//            machine.start();
//            machine.getExtendedState().getVariables().put("orderId", id); // 绑定订单ID到上下文
            return machine;
        });
    }


}
